import datetime
import json

from django.shortcuts import render
from django.http import HttpResponse, JsonResponse
from django.utils import timezone
from django.views.decorators.http import require_http_methods

from .modules import ExceptionPrinter
from .modules.DataGetter import DataGetter
from django.core import serializers
from .models import Device, Data, Datapack
from apscheduler.schedulers.background import BackgroundScheduler

dg = DataGetter()
scheduler = BackgroundScheduler()
scheduler.start()
useDemoData = False


def periGetData(deviceNumber, jobid):
	print("{} executing.".format(jobid))
	dg.getData(deviceNumber)


def periGetDemoData(deviceNumber, jobid):
	print("{}[Demo] executing.".format(jobid))
	dg.getDemoData(deviceNumber)


# dg.getDevices()
# dg.getData("0F44178BF214")
# dg.getData("0F44178BF780")


def index(request):
	return HttpResponse("SensorMonitor index page.")


@require_http_methods(['GET'])
def getDevices(request):
	# 定义响应体
	response = {
		'status': 'success',
		'devices': [],
		'device': None
	}
	try:
		# 检索所有设备
		raw_data = Device.objects.all()
		# 针对单个设备信息的数据解析与打包
		if request.GET.get("deviceNumber") is not None:
			raw_data = raw_data.get(device_number__exact=request.GET.get("deviceNumber"))
			device = raw_data.__dict__
			device.pop("_state")
			device.pop("id")
			response['device'] = device
			# 响应请求
			return JsonResponse(response)

		# 针对所有设备信息的数据解析与打包
		devices = []
		for device in json.loads(serializers.serialize('json', raw_data)):
			dev = device['fields'].copy()
			dev['dimensions'] = []
			dimensions = device['fields']['dimensions'].split(',')
			for dimension in dimensions:
				dev['dimensions'].append(dimension)
			devices.append(dev)
		response['devices'] = devices
		# 响应请求
		return JsonResponse(response)
	except Exception as e:
		return JsonResponse({
			'status': 'failed',
			'msg': str(e)
		})


@require_http_methods(['GET'])
def getData(request, deviceNumber):
	# 定义响应体
	response = {
		'status': 'success',
		'datapacks': []
	}
	try:
		# 检索指定设备的数据包，结果按时间降序排列
		raw_datapacks = Datapack.objects.filter(device__device_number__exact=deviceNumber).filter(time__gte=datetime.datetime.now(tz=timezone.get_current_timezone()) - datetime.timedelta(hours=1)).order_by('-time')
		try:
			# 取出查询条目数参数count
			dataCount = int(request.GET.get('count'))
			# 检索结果的前count条作为返回的数据
			if dataCount < len(raw_datapacks):
				raw_datapacks = raw_datapacks[0:dataCount]
		except Exception as e:
			ExceptionPrinter.printException(e)
		# 定义数据包集合
		datapacks = []
		for dp in raw_datapacks:
			# 根据数据包检索数据并打包成一个数据包
			raw_data = Data.objects.filter(datapack__exact=dp)
			data = []
			for rd in raw_data:
				# data.append(serializers.serialize('json', rd))
				rd_dict = rd.__dict__
				rd_dict.pop('_state')
				rd_dict.pop('id')
				rd_dict.pop('hash')
				rd_dict.pop('device_id')
				data.append(rd.__dict__)
			# 数据包添加到数据包集合
			datapacks.append({
				'time': dp.time,
				'deviceNumber': dp.device.device_number,
				'data': data
			})
		# 在响应体中加入数据包集合
		response['datapacks'] = datapacks
		# 响应请求
		return JsonResponse(response)
	except Exception as e:
		ExceptionPrinter.printException(e)
		return JsonResponse({
			'status': 'failed',
			'msg': str(e)
		})


def login(request):
	return JsonResponse({
		'status': 'success' if dg.login() else 'failed'
	})


def generateDemoData(request, deviceNumber):
	return JsonResponse({
		'status': 'success' if dg.getDemoData(deviceNumber) else 'failed'
	})


def updateData(request, deviceNumber):
	return JsonResponse({
		'status': 'success' if dg.getData(deviceNumber) else 'failed'
	})


def updateDevices(request):
	return JsonResponse({
		'status': 'success' if dg.getDevices() else 'failed'
	})


def getPeriUpdateStatus(request, deviceNumber):
	try:
		# 根据设备序列号检索设备
		device = Device.objects.get(device_number__exact=deviceNumber)
		# 构造计划任务ID
		jobid = "peri_update_{}".format(deviceNumber)
		intervalMinutes = 0
		# 查询在运行的计划任务
		if scheduler.get_job(jobid) is None:
			device.peri_update = False
		else:
			device.peri_update = True
			intervalStr = str(scheduler.get_job(jobid).trigger).replace("interval[", "").replace("]", "")
			intervalMinutes = datetime.datetime.strptime(intervalStr, "%H:%M:%S").minute
		# 将自动更新状态入库
		device.save()
		# 响应请求
		return JsonResponse({
			"status": "success",
			"periUpdateStatus": Device.objects.get(device_number__exact=deviceNumber).peri_update,
			"minutes": intervalMinutes
		})
	except Exception as e:
		ExceptionPrinter.printException(e)
		return JsonResponse({
			"status": "failed",
			"msg": str(e)
		})


def periUpdateUseDemo(request):
	global useDemoData
	useDemoData = True
	return JsonResponse({
		"status": 'success'
	})


def periUpdateUseFact(request):
	global useDemoData
	useDemoData = False
	return JsonResponse({
		"status": "success"
	})


def periUpdateUse(request):
	return JsonResponse({
		"status": "success",
		"use": "demo" if useDemoData else "fact"
	})


@require_http_methods(['GET'])
def periUpdateStart(request, deviceNumber):
	# 获取更新间隔参数
	minutes = request.GET.get('minutes')
	seconds = request.GET.get('seconds')
	# 构造计划任务ID
	jobid = 'peri_update_{}'.format(deviceNumber)
	try:
		# 创建计划任务
		if minutes is None and seconds is not None:
			seconds = int(seconds)

		elif minutes is not None and seconds is None:
			seconds = int(minutes) * 60
		else:
			return JsonResponse({
				'status': 'failed',
				'msg': 'invalid interval'
			})

		if useDemoData:
			scheduler.add_job(periGetDemoData, 'interval', id=jobid, seconds=seconds, args=[deviceNumber, jobid])
			print('added job of {} [use demo].'.format(jobid))
		else:
			scheduler.add_job(periGetData, 'interval', id=jobid, seconds=seconds, args=[deviceNumber, jobid])
			print('added job of {} [use fact].'.format(jobid))

		scheduler.print_jobs()
		# 自动更新状态入库
		device = Device.objects.get(device_number__exact=deviceNumber)
		device.peri_update = True
		device.save()
		# 响应请求
		return JsonResponse({
			'status': 'success',
		})
	except Exception as e:
		ExceptionPrinter.printException(e)
		return JsonResponse({
			'status': 'failed',
			'msg': str(e)
		})


def periUpdateStop(request, deviceNumber):
	# 构造计划任务ID
	jobid = 'peri_update_{}'.format(deviceNumber)
	try:
		# 暂停计划任务
		scheduler.pause_job(jobid)
		# 移除计划任务
		scheduler.remove_job(jobid)
		print('removed job of {}.'.format(jobid))
		scheduler.print_jobs()
		# 自动更新状态入库
		device = Device.objects.get(device_number__exact=deviceNumber)
		device.peri_update = False
		device.save()
		# 响应请求
		return JsonResponse({
			'status': 'success',
		})
	except Exception as e:
		ExceptionPrinter.printException(e)
		return JsonResponse({
			'status': 'failed',
			'msg': str(e)
		})
